package thread;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: wx
 * Date: 2024-01-06
 * Time: 19:35
 */


import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.BlockingQueue;

/**多线程案例
 *
 * 阻塞队列
 * 队列 先进先出
 *
 * 阻塞队列,就是基于普通队列做出的扩展(先进先出)
 * 1.线程安全
 * 2.具有阻塞特性
 *    a)如果针对一个已经满了的队列进行入队列,此时入队列操作就会阻塞,一直阻塞到队列不满(其他线程出队列元素)之后
 *    b)如果针对一个已经空了的队列进行出队列,此时出队列操作就会阻塞,一直阻塞带队列不空(其他线程入队列元素)之后
 *
 *    基于阻塞队列,就可以实现: '生产者-消费者'模型
 *
 *    过年的时候,吃年夜饭就是吃饺子.
 *    包饺子的流程 : 1.和面
 *                2.擀饺子皮
 *                3.包饺子
 *    先和面,在共同完成 包饺子 和 擀饺子皮
 *      三个人来完成包饺子,明显比一个人会快很多
 *      在 擀饺子皮的时候 擀面杖一般来说只有一个
 *      三个线程需要竞争 擀面杖 存在锁竞争这个问题
 *      为了解决这个问题,就可以分工合作
 *      一个擀 两个包
 *      这个就避免了竞争,此时就不需要锁竞争,效率会更快
 *      这里的分工协作就构成了 生产者-消费者模型
 *      擀饺子皮的线程的就是生产者
 *    另外两个包饺子的线程就是消费者
 *    我们也需要一个桌子 来放置饺子皮
 *              (桌子的角色就相当于"阻塞队列")
 *   假设 擀饺子皮太快,包的慢.导致桌子上的饺子皮越来越多,就需要擀的人停下来等一等
 *       擀饺子皮太慢,报的快.导致桌子上的饺子皮越来越多,就需要包的人停下来等一等
 *       这里的桌子跟 "阻塞队列" 的作用是差不多的
 *
 *       生产者消费者模型,在实际开发中是非常有意义的
 *
 *       1. 引入这个模型 ,就可以更好做到 解耦合(把代码的耦合程度 由高降低)
 *               实际开发中,经常会涉及到 "分布式系统". 服务器整个功能不是由服务器全部完成的.而是每个服务器负责一部分功能,
 *             通过服务器之间的网络通信,最终完成整个功能
 *           阻塞队列引入的代价是什么?
 *            1)需要引入更多的硬件资源
 *            2)上述描述的 阻塞队列 ,并非是简单的数据结构.而是基于这个数据结构实现的服务器程序,
 *              又被部署到单独的主机上了 (又被称为 消息队列 "message queue  mq")
 *            3)整个系统的结构更复杂了.你要维护的服务器更多了
 *            4)效率.引入中间商,还是有差价的.请求从 A 发出来到 B 收到,这个过程中就经历队列的转发
 *              这个过程也是有一定的开销的
 *       2. 削峰填谷
 *            三峡大坝: 功在当下,利在千秋
 *            98年,全国性质大洪水(人民子弟兵,用血肉之躯,来抗险救灾)
 *            2021年 也有一个非常大的洪水灾害 长江上游的降雨量比 98 年不遑多让
 *            郑州 被暴雨淹了 长江开始发洪水
 *            抗洪,虽然人民子弟兵也出动了,但是就感觉轻描淡写就搞定了
 *          三峡大坝在里边起到了重要的作用
 *
 *                             外网                                              机房
 *
 *      众多服务器                                  |
 *       服务器 A                                  |                          用户服务器  E
 *                                                |
 *                                                |
 *       服务器 B        ->  请求                   |      入口服务器 D
 *                                                |    工作简单,消耗资源少
 *                                                |
 *       服务器 C                                  |                          商品服务器  F
 *
 *   一旦外界的请求出现突发峰值,就会使 B C 直接给挂了
 *   使用生产者消费者模型就可以很好地解决这个问题
 *
 *
 *  *                             外网                                                      机房
 *  *
 *  *      众多服务器                                  |
 *  *       服务器 A                                  |                                  用户服务器  E
 *  *                                                |                                   /
 *  *                                                |                                  /
 *  *       服务器 B        ->  请求                   |      入口服务器 D        阻塞队列/消息队列
 *  *                                                |    工作简单,消耗资源少               \
 *  *                                                |                                   \
 *  *       服务器 C                                  |       外界请求出现峰值              商品服务器  F
 *  *                                                        是由队列来承担峰值的
 *  *                                                        B C 任然按照之前的速度来读取
 *
 */

/*
*Java 标准库里边提供了现成的阻塞队列数据结构
*                      ArraryBlockQueue
* BlockingQueue        LinkedBlockQueue
* 是一个 interface      PriorityBLockQueue
*
*
*
*/


public class ThreadDemo27 {

    public static void main(String[] args) {

    }
    public static void main1(String[] args) {
        BlockingQueue<String> queue = new ArrayBlockingQueue<>(100);
        try {
            queue.put("aaa");
                // put 和 offer 一样都是入队列,
                // 但是 put 是带有阻塞功能的, offer 没有阻塞功能(队列满了会返回结果)
            String elem = queue.take();
                                // take 方法用来 出队列,也是带有阻塞功能的
            System.out.println("elem = " + elem);
            elem = queue.take();
            System.out.println("elem = " + elem);
            //阻塞队列没有提供带有阻塞功能的获取队首元素的方法
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
    //上述是序幕
}
